Ivan Gotovchits edited this page Mar 3, 2016 · 7 revisions

Setting up Emacs

There is a new initiative in the community -- user-setup package, I personally didn't try it, but on a first glance it looks pretty nice and prominent. You can try it yourself on your risk, and actually I'm encouraging everyone to do this, but here I will share my setup, as it is what I've tested personally. But, maybe later we will rewrite this page to user-setup.


Our setup will depend on three packages:

  • Tuareg - major mode for editing OCaml source code;
  • Merlin - Tuareg minor mode that adds incremental compilation, intellisense-like completion, and other neat stuff;
  • ocp-indent - external indentation program that knows OCaml very well in comparison with the default tuaregs indentation engine that is just a set of regular expressions.

To install them from OPAM use:

opam install tuareg merlin ocp-indent

You will also need auto-complete mode for EMacs, available in elpa and melpa. To enable this (and also marmalade) you need the following at the start of your .emacs:

(setq package-archives '(("gnu" . "http://elpa.gnu.org/packages/")
                         ("marmalade" . "http://marmalade-repo.org/packages/")
                         ("melpa" . "http://melpa.milkbox.net/packages/")))

After this issue M-x package-list-packages and find out company package with the latest version, and install it.

Main configuration file

After everything is ready, you can store the following in ocaml.el, put it into your emacs search path, and load in .emacs with (require 'ocaml) instruction. (Of course, you can just copy-paste this directly into your .emacs, but I prefer to keep it clean).

(defun opam-path (path)
  (let ((opam-share-dir
          "echo -n `opam config var share`")))
    (concat opam-share-dir "/" path)))

(add-to-list 'load-path (opam-path "emacs/site-lisp"))
(add-to-list 'load-path (opam-path "tuareg"))

(load "tuareg-site-file")

(require 'ocp-indent)
(require 'merlin)
(require 'company)
(add-to-list 'company-backends 'merlin-company-backend)
(add-hook 'merlin-mode-hook 'company-mode)

(define-key merlin-mode-map (kbd "C-c TAB") 'company-complete)
(define-key merlin-mode-map (kbd "C-c C-d") 'merlin-document)
(define-key merlin-mode-map (kbd "C-c d") 'merlin-destruct)

(setq merlin-completion-with-doc t)
(setq merlin-use-auto-complete-mode nil)
(setq tuareg-font-lock-symbols t)
(setq merlin-command 'opam)
(setq merlin-locate-preference 'mli)

(defun change-symbol (x y)
  (setcdr (assq x tuareg-font-lock-symbols-alist) y))

(defun ocp-indent-buffer ()
    (ocp-indent-region (region-beginning)

(add-hook 'tuareg-mode-hook
          (lambda ()
            (local-set-key (kbd "C-c c") 'recompile)
            (local-set-key (kbd "C-c C-c") 'recompile)
            (add-hook 'before-save-hook 'ocp-indent-buffer nil t)))

(defun opam-env ()
  (interactive nil)
  (dolist (var
           (car (read-from-string
                 (shell-command-to-string "opam config env --sexp"))))
    (setenv (car var) (cadr var))))

(provide 'ocaml)

Configuring Merlin

Merlin should work out of box, but it only knows vanilla OCaml by default. So, we need to teach him to use BAP and Core_kernel. Merlin is pretty clever, so it won't take to much time, you just need to create .merlin file in the project root, and describe what libraries are you using and how you structured your project. Something like this should work:

PKG core_kernel
PKG bap
PKG ocamlgraph

B _build
FLG -short-paths
FLG -w -4-33-40-41-42-43-34-44

Note that Merlin is already configured for bap-plugins and bap repositories. If your're working in this repositories and you want to add some options to your subproject, like adding new package or flag, then create a .merlin file in your folder and add REC line into it, this will automatically include parent .merlin, e.g.,

PKG cmdliner

Sometimes Merlin gets very confused, especially when after you've made opam update. In that case it can be healed by killing him and starting from scratch with M-x merlin-restart-process command.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.