Emacs configuration for merlin-lsp, the OCaml LSP server

Since the , there is an implementation of LSP server integrated into merlin. It's not the first LSP server for OCaml. There are at least two other servers that exist. But having one officially integrated in merlin provides a few guaranties.

I built an extension to merlin, merlin-eldoc, that provides some facilities on top of what comes in the default merlin. Especially highlighting all the occurrences of a value, jumping between the occurrences, and automatically display its type. Using merlin-lsp, it should be possible to have all those nice features plus the original ones from merlin with very little configuration.

Emacs has two LSP clients. Here I will describe how to configure lsp-mode, which in my experience works better than eglot.

Note that lsp-ocaml, a configuration module for lsp-mode, is a deprecated project. Now lsp-mode is enough.

First step is to install merlin-lsp. There is no package published on opam yet. So it has to be pinned.

opam pin add merlin-lsp.dev https://github.com/ocaml/merlin.git

Then comes the Emacs part. lsp-mode can be installed from melpa. And works with emacs25+. The basic configuration to get to a working point is short.

( require ' lsp-mode ) ( lsp-register-client ( make-lsp-client :new-connection ( lsp-stdio-connection ' ( "opam" "exec" "--" "ocamlmerlin-lsp" ) ) :major-modes ' ( caml-mode tuareg-mode ) :server-id 'ocamlmerlin-lsp ) )

With those lines in your Emacs configuration, you must now have the lsp command available. If you visit an OCaml file and run it, it will try to connect to the server.

During the connection to merlin-lsp, it should create a buffer name *lsp-log* . Its content in case of successful connection looks like this:

Command "ocaml-language-server --stdio" is not present on the path. Command "opam exec -- ocamlmerlin-lsp" is present on the path. Found the following clients for /home/louis/Code/demo/src/main.ml: (server-id ocamlmerlin-lsp, priority 0) The following clients were selected based on priority: (server-id ocamlmerlin-lsp, priority 0)

Normally, lsp-mode should have configured xref automatically and the most important features of merlin should already be available.

Jumping from a value to its definition, using M-. or xref-find-definitions or lsp-find-definition (the equivalent of merlin-locate ).

or or (the equivalent of ). Listing the occurrences of a value, with M.? or xref-find-references or lsp-find-references (the equivalent of merlin-occurrences ).

or or (the equivalent of ). Displaying the type of the value at point, with a message in the minibuffer (relying on eldoc) or by calling lsp-describe-thing-at-point (the equivalent of merlin-type-enclosing ).

(the equivalent of ). Listing the errors in the current file, with flycheck or flymake.

Completion of variable and function names.

This list is not exhaustive. It even has features that are not available with the usual merlin. lsp-goto-type-definition is like locate, but for the type of the expression. lsp-lens-show is the equivalent of the code lens in vscode.

Some extensions to lsp-mode are available, to have a fancier display or nicer completion.

There are a few things in the default configuration of lsp-mode that I don't like. Especially, it tries to display the type at point even when the point is not on some code. So I came up with a few changes, mostly imported from merlin-eldoc. I am publishing here my whole configuration, relying on use-package . I hope it can help you to start using merlin-lsp.

Don't hesitate to give a hand to implement missing features in merlin-lsp! It is usually not as hard as you imagine.