This year I started consolidating all the major modes by using
apheleia for all the programming language I use. The switch from OCaml’s
merlin-mode was surprisingly painless.
Let’s start with the default major modes that provide syntax highlighting and a few other things. I have
tuareg for OCaml,
dune-format to format dune files and
reason-mode for ReasonML.
(use-package tuareg :ensure t :custom (tuareg-opam-insinuate t) :config) (use-package dune-format :ensure t) (use-package reason-mode :ensure t)
lsp-mode setup is the same for every language so I get a consistent experience. I am using
ocamllsp as the LSP server implementation, this is the one that the official VS Code extension uses as well.
(defun my-lsp-fix-buffer () "Formats buffer and organizes imports." (interactive) (lsp-organize-imports) (lsp-format-buffer)) (use-package lsp-mode :ensure t :after flycheck :commands lsp :bind (("C-c l n" . flycheck-next-error) ("C-c l d" . lsp-find-definition) ("C-c l r" . lsp-find-references) ("C-c l h" . lsp-describe-thing-at-point) ("C-c l i" . lsp-find-implementation) ("C-c l R" . lsp-rename) ("C-c l o" . my-lsp-fix-buffer)) :hook ((tuareg-mode . lsp) (caml-mode . lsp) (reason-mode . lsp) (before-save . lsp-organize-imports)) :custom (lsp-lens-enable t) (lsp-log-io nil) (lsp-headerline-breadcrumb-enable nil) :config (lsp-enable-which-key-integration t) (lsp-register-client (make-lsp-client :new-connection (lsp-stdio-connection '("opam" "exec" "--" "ocamllsp")) :major-modes '(caml-mode tuareg-mode reason-mode) :server-id 'ocamllsp)))
For my formatting needs I use the outstanding
apheleia package. This package is great, especially for slow formatters. With
ocamlformat you won’t get all the benefits because it’s quite fast.
Apheleia runs the formatting on a buffer in the background and patches
the current buffer asynchronously. The cursor remains at the same location in the code, which makes it easy to keep track of what is going on.
(use-package apheleia :ensure t :hook (caml-mode . apheleia-mode) (tuareg-mode . apheleia-mode) (reason-mode . apheleia-mode) :config (setf (alist-get 'ocamlformat apheleia-formatters) '("opam" "exec" "--" "ocamlformat" "--impl" "-")) (setf (alist-get 'refmt apheleia-formatters) '("opam" "exec" "--" "refmt")) (setf (alist-get 'tuareg-mode apheleia-mode-alist) '(ocamlformat)) (setf (alist-get 'reason-mode apheleia-mode-alist) '(refmt)))
I don’t use
lsp-mode on its own does the trick combined with