Using Utop in Emacs

by Mads Hartmann - 05 Jan 2014
utop is an improved toplevel for OCaml. It can run in a terminal or in Emacs. It supports line edition, history, real-time and context sensitive completion, colors, and more.

I've found utop to be a really nice toplevel for playing around with OCaml. Especially being able to evaluate code straight from an Emacs buffer is wonderful. However, as soon as you start using it on larger projects you will find that in a lot of cases it won't be able to evaluate the code in your buffer as it depends on various opam packages and modules you've defined in your project.

Luckily there is a way to make utop aware of the opam packages that you depend on and the modules you've defined in your project. This is a short blog post to explain how. I've also created a very small example project to provide concrete examples.

Note: This is the 2nd iteration. The setup was vastly simplified on November 8 2014. The previous version can be found here.

1 Loading the appropriate packages

If you fire up utop and invoke #use "topfind";; you will have a new directive named #require that you can use to load your opam packages into the toplevel (e.g. #require "batteries";;)

This is really neat and convenient when you want to play around with a specific package, but if you use a lot of modules it's still quite tedious (we use 24 in one of our OCaml projects at issuu.)

Fortunately utop makes it possible to put these directives (or anything else you could type in the toplevel) in a file and have utop load it upon boot. If there's a file named .ocamlinit in the folder where you invoke utop it will load that, otherwise you can specify a file path using the -init option.

So if you simply create a .ocamlinit file which contains the appropriate #use and #require statements then you will have everything loaded and ready when utop has launched. See this .ocamlinit for a concrete example.

2 Making utop aware of your compiled sources

The other thing to solve is figuring out how to tell utop where to look for your bytecode. There are two ways to achieve this. You can use the #directory directive in the toplevel (or your .ocamlinit file) or you can specify it as command line argument when invoking utop using -I <dir>. Again See this .ocamlinit for a concrete example.

3 Using it from inside of Emacs

The last piece of the puzzle is a bit of Emacs configuration.

You need to tell Emacs to use the -init option when starting the utop buffer. You can do this through the utop-command variable so you won't have to type it in manually every time you invoke M-x utop. I prefer setting it in the .dir-locals file of my ocaml projects1. You can see a concrete example here. An example is shown below.

((tuareg-mode .
    ((utop-command . "utop -emacs -init ~/dev/backend-similarity/.ocamlinit"))))

Now you can just open an OCaml source file and hit M-x utop to get a properly configured utop toplevel buffer. You can feed code to your utop session using C-x C-e. This makes it refreshingly easy to play around with smaller pieces of OCaml code straight from your buffer.

Footnotes:

1

Support for this is currently on master but a new release hasn't been pushed to opam yet. See this PR.