2017-08-04 09:47:52 +00:00
|
|
|
utop — a universal toplevel (i.e., REPL) for OCaml
|
|
|
|
==================================================
|
2012-10-17 09:32:11 +00:00
|
|
|
|
2017-08-04 09:47:52 +00:00
|
|
|
utop is an improved toplevel (i.e., Read-Eval-Print Loop) for
|
|
|
|
OCaml. It can run in a terminal or
|
2017-03-22 17:33:15 +00:00
|
|
|
in Emacs. It supports line editing, history, real-time and context
|
2012-10-17 09:32:11 +00:00
|
|
|
sensitive completion, colors, and more.
|
|
|
|
|
2017-08-04 09:47:52 +00:00
|
|
|
It integrates with the Tuareg and typerex modes in Emacs.
|
2012-10-17 09:32:11 +00:00
|
|
|
|
2018-08-21 22:22:45 +00:00
|
|
|
[![Travis build Status](https://travis-ci.org/ocaml-community/utop.svg?branch=master)](https://travis-ci.org/ocaml-community/utop)
|
2016-04-08 09:16:55 +00:00
|
|
|
|
2018-09-24 16:48:27 +00:00
|
|
|
![Screenshot](screenshot.png)
|
|
|
|
|
2013-01-19 04:29:58 +00:00
|
|
|
Installation via opam
|
|
|
|
---------------------
|
|
|
|
|
|
|
|
The easiest and recommended way of installing utop is via
|
2014-10-20 16:13:41 +00:00
|
|
|
[opam](https://opam.ocaml.org/):
|
2013-01-19 04:29:58 +00:00
|
|
|
|
|
|
|
$ opam install utop
|
|
|
|
|
|
|
|
If you want to build it manually, you should install all the
|
|
|
|
dependencies listed in the next section.
|
|
|
|
|
2012-10-17 09:32:11 +00:00
|
|
|
Dependencies
|
|
|
|
------------
|
|
|
|
|
2019-05-26 08:21:02 +00:00
|
|
|
* [OCaml](http://caml.inria.fr/ocaml/) (>= 4.03.0)
|
2019-01-14 18:50:32 +00:00
|
|
|
* [Dune](http://github.com/ocaml/dune)
|
2014-10-20 16:13:41 +00:00
|
|
|
* [findlib](http://projects.camlcity.org/projects/findlib.html) (>= 1.4.0)
|
2015-05-23 22:52:42 +00:00
|
|
|
* [cppo](http://mjambon.com/cppo.html) (>= 1.0.1)
|
2012-10-17 09:32:11 +00:00
|
|
|
* [react](http://erratique.ch/software/react)
|
|
|
|
* [lwt](http://ocsigen.org/lwt/) (>= 2.4.0) built with react support
|
|
|
|
* [Camomile](http://github.com/yoriyuki/Camomile) (>= 0.8)
|
2019-05-26 08:21:02 +00:00
|
|
|
* [zed](http://github.com/diml/zed) (>= 2.0)
|
|
|
|
* [lambda-term](http://github.com/diml/lambda-term) (>= 2.0)
|
2012-10-17 09:32:11 +00:00
|
|
|
|
2013-01-19 04:29:58 +00:00
|
|
|
Installation from sources
|
|
|
|
-------------------------
|
2012-10-17 09:32:11 +00:00
|
|
|
|
2012-10-20 09:43:05 +00:00
|
|
|
To build and install utop:
|
2012-10-17 09:32:11 +00:00
|
|
|
|
|
|
|
$ make
|
|
|
|
$ make install
|
|
|
|
|
|
|
|
### Documentation and manual pages _(optional)_
|
|
|
|
|
2017-03-16 00:05:01 +00:00
|
|
|
To build the documentation (currently broken):
|
2012-10-17 09:32:11 +00:00
|
|
|
|
|
|
|
$ make doc
|
|
|
|
|
|
|
|
It will then be installed by `make install`.
|
|
|
|
|
2014-10-20 16:16:39 +00:00
|
|
|
### Tests _(optional)_
|
2012-10-17 09:32:11 +00:00
|
|
|
|
2017-03-16 00:05:01 +00:00
|
|
|
To build and execute tests (currently broken):
|
2012-10-17 09:32:11 +00:00
|
|
|
|
|
|
|
$ make test
|
|
|
|
|
|
|
|
Usage
|
|
|
|
-----
|
|
|
|
|
|
|
|
To use utop, simply run:
|
|
|
|
|
|
|
|
$ utop
|
|
|
|
|
|
|
|
utop display a bar after the prompt which is used to show possible
|
2013-11-20 10:29:10 +00:00
|
|
|
completions in real-time. You can navigate in it using `M-left` and
|
|
|
|
`M-right`, and select one completion using `M-tab`. The `M` denotes
|
|
|
|
the meta key, which is `Alt` most of the time.
|
2012-10-17 09:32:11 +00:00
|
|
|
|
|
|
|
Customization
|
|
|
|
-------------
|
|
|
|
|
2013-07-08 10:12:07 +00:00
|
|
|
### Colors
|
|
|
|
|
2012-10-17 09:32:11 +00:00
|
|
|
To add colors to utop, copy one of the files `utoprc-dark` or
|
|
|
|
`utoprc-light` to `~/.utoprc`. `utoprc-dark` is for terminals with
|
|
|
|
dark colors (such as white on black) and `utoprc-light` is for
|
|
|
|
terminals with light colors (such as black on white).
|
|
|
|
|
2013-07-08 10:12:07 +00:00
|
|
|
### Prompt
|
|
|
|
|
|
|
|
You can customize the prompt of utop by setting the reference
|
2012-10-17 09:32:11 +00:00
|
|
|
`UTop.prompt`.
|
|
|
|
|
2019-05-01 02:53:07 +00:00
|
|
|
To turn off all colors and remove the line above the prompt
|
2020-02-22 20:53:20 +00:00
|
|
|
that lists time, etc., add this to ~/.config/utop/init.ml:
|
2019-05-01 02:53:07 +00:00
|
|
|
```OCaml
|
2020-02-22 20:53:20 +00:00
|
|
|
#utop_prompt_dummy;;
|
2019-05-01 02:53:07 +00:00
|
|
|
```
|
2020-02-22 20:53:20 +00:00
|
|
|
To turn off the line of boxes listing possible completions that appears under
|
|
|
|
the prompt, add this to ~/.config/utop/init.ml:
|
2019-05-01 02:53:07 +00:00
|
|
|
```OCaml
|
|
|
|
UTop.set_show_box false
|
|
|
|
```
|
|
|
|
|
2013-07-08 10:12:07 +00:00
|
|
|
### Key bindings
|
|
|
|
|
|
|
|
Key bindings in the terminal can be changed by writing a
|
|
|
|
`~/.lambda-term-inputrc` file. For example:
|
|
|
|
|
|
|
|
[read-line]
|
|
|
|
C-left: complete-bar-prev
|
|
|
|
C-right: complete-bar-next
|
|
|
|
C-down: complete-bar
|
|
|
|
|
|
|
|
If manual pages are correctly installed you can see a description of
|
|
|
|
this file by executing:
|
|
|
|
|
|
|
|
$ man 5 lambda-term-inputrc
|
|
|
|
|
2014-10-28 00:40:23 +00:00
|
|
|
### UTop API
|
|
|
|
|
|
|
|
UTop exposes several more settings through its API; see
|
2018-09-18 15:56:28 +00:00
|
|
|
[documentation](http://ocaml-community.github.io/utop).
|
2014-10-28 00:40:23 +00:00
|
|
|
|
2012-10-17 09:32:11 +00:00
|
|
|
Integration with emacs
|
|
|
|
----------------------
|
|
|
|
|
2016-02-09 17:16:33 +00:00
|
|
|
### Main setup
|
|
|
|
|
2013-09-06 12:28:17 +00:00
|
|
|
To use utop in emacs, first you need to make sure emacs can find the
|
2016-02-09 17:16:33 +00:00
|
|
|
command `utop` and the file `utop.el`. `utop.el` is available through
|
|
|
|
[melpa](https://melpa.org/), so `M-x package-install RET utop RET`
|
|
|
|
should do.
|
|
|
|
|
|
|
|
If this doesn't work and you installed utop via opam, you can add this
|
|
|
|
to your `~/.emacs`:
|
|
|
|
|
2020-01-03 22:26:17 +00:00
|
|
|
```elisp
|
2016-02-09 17:16:33 +00:00
|
|
|
;; Add the opam lisp dir to the emacs load path
|
|
|
|
(add-to-list
|
|
|
|
'load-path
|
|
|
|
(replace-regexp-in-string
|
|
|
|
"\n" "/share/emacs/site-lisp"
|
|
|
|
(shell-command-to-string "opam config var prefix")))
|
|
|
|
|
|
|
|
;; Automatically load utop.el
|
|
|
|
(autoload 'utop "utop" "Toplevel for OCaml" t)
|
|
|
|
```
|
|
|
|
|
|
|
|
In any case, if you installed utop via opam you should add this to
|
|
|
|
your `~/.emacs`:
|
|
|
|
|
2020-01-03 22:26:17 +00:00
|
|
|
```elisp
|
2016-02-09 17:16:33 +00:00
|
|
|
;; Use the opam installed utop
|
|
|
|
(setq utop-command "opam config exec -- utop -emacs")
|
2019-12-21 06:01:01 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
If you use `dune` and want to launch `dune utop` in emacs, you
|
|
|
|
should add this to your `~/.emacs`:
|
|
|
|
|
2020-01-03 22:26:17 +00:00
|
|
|
```elisp
|
2019-12-21 06:01:01 +00:00
|
|
|
(setq utop-command "opam config exec -- dune utop . -- -emacs")
|
2016-02-09 17:16:33 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
This was tested with opam 1.2. For older versions of opam, you can
|
|
|
|
copy&paste this to your `~/.emacs`:
|
2012-10-17 09:32:11 +00:00
|
|
|
|
2020-01-03 22:26:17 +00:00
|
|
|
```elisp
|
2013-09-06 12:28:17 +00:00
|
|
|
;; Setup environment variables using opam
|
|
|
|
(dolist (var (car (read-from-string (shell-command-to-string "opam config env --sexp"))))
|
|
|
|
(setenv (car var) (cadr var)))
|
|
|
|
|
|
|
|
;; Update the emacs path
|
2014-08-22 11:55:33 +00:00
|
|
|
(setq exec-path (append (parse-colon-path (getenv "PATH"))
|
|
|
|
(list exec-directory)))
|
2013-09-06 12:28:17 +00:00
|
|
|
|
|
|
|
;; Update the emacs load path
|
2014-08-22 11:55:33 +00:00
|
|
|
(add-to-list 'load-path (expand-file-name "../../share/emacs/site-lisp"
|
|
|
|
(getenv "OCAML_TOPLEVEL_PATH")))
|
2013-09-06 12:28:17 +00:00
|
|
|
|
|
|
|
;; Automatically load utop.el
|
2012-10-17 09:32:11 +00:00
|
|
|
(autoload 'utop "utop" "Toplevel for OCaml" t)
|
|
|
|
```
|
|
|
|
|
2016-02-09 17:16:33 +00:00
|
|
|
### Usage
|
|
|
|
|
2013-09-06 12:28:17 +00:00
|
|
|
Then you can execute utop inside emacs with: `M-x utop`.
|
2013-06-19 16:23:48 +00:00
|
|
|
|
2015-01-05 12:21:50 +00:00
|
|
|
utop also ships with a minor mode that has the following key-bindings
|
2012-10-17 09:32:11 +00:00
|
|
|
|
2015-01-05 12:21:50 +00:00
|
|
|
| key-binding | function | Description |
|
|
|
|
|-------------|-------------------|------------------------------|
|
2015-01-11 12:20:03 +00:00
|
|
|
| C-c C-s | utop | Start a utop buffer |
|
2015-01-05 12:21:50 +00:00
|
|
|
| C-x C-e | utop-eval-phrase | Evaluate the current phrase |
|
|
|
|
| C-x C-r | utop-eval-region | Evaluate the selected region |
|
|
|
|
| C-c C-b | utop-eval-buffer | Evaluate the current buffer |
|
|
|
|
| C-c C-k | utop-kill | Kill a running utop process |
|
|
|
|
|
|
|
|
You can enable the minor mode using `M-x utop-minor-mode`, or you can
|
2016-02-09 17:16:33 +00:00
|
|
|
have it enabled by default with the following configuration:
|
2015-01-05 12:21:50 +00:00
|
|
|
|
2020-01-03 22:26:17 +00:00
|
|
|
```elisp
|
2015-01-05 12:21:50 +00:00
|
|
|
(autoload 'utop-minor-mode "utop" "Minor mode for utop" t)
|
|
|
|
(add-hook 'tuareg-mode-hook 'utop-minor-mode)
|
|
|
|
```
|
|
|
|
|
2015-01-12 10:06:08 +00:00
|
|
|
If you plan to use utop with another major-mode than tuareg, replace
|
|
|
|
`tuareg-mode-hook` by the appropriate hook. The utop minor mode will
|
|
|
|
work out of the box with these modes: `tuareg-mode`, `caml-mode` and
|
|
|
|
`typerex-mode`. For other modes you will need to set the following
|
|
|
|
three variables:
|
|
|
|
|
|
|
|
- `utop-skip-blank-and-comments`
|
|
|
|
- `utop-skip-to-end-of-phrase`
|
|
|
|
- `utop-discover-phrase`
|
2012-10-17 09:32:11 +00:00
|
|
|
|
2015-01-05 12:21:50 +00:00
|
|
|
You can also complete text in a buffer using the environment of the
|
|
|
|
toplevel. For that bind the function `utop-edit-complete` to the key
|
|
|
|
you want.
|
2012-10-29 09:48:35 +00:00
|
|
|
|
2013-02-23 17:13:36 +00:00
|
|
|
Common error
|
|
|
|
------------
|
|
|
|
|
|
|
|
If you get this error when running utop in a terminal or in emacs this
|
|
|
|
means that the environment variable `CAML_LD_LIBRARY_PATH` is not set
|
|
|
|
correctly:
|
|
|
|
|
|
|
|
Fatal error: cannot load shared library dlllwt-unix_stubs
|
|
|
|
Reason: dlopen(dlllwt-unix_stubs.so, 138): image not found
|
|
|
|
|
|
|
|
It shall point to the directory `stublibs` inside your ocaml installation.
|
|
|
|
|
2019-01-31 10:37:01 +00:00
|
|
|
Automatically installing toplevel printers
|
|
|
|
------------------------------------------
|
|
|
|
|
|
|
|
Utop will automatically install toplevel printers for custom
|
|
|
|
types if their interface file is marked with an
|
|
|
|
`[@@ocaml.toplevel_printer]` attribute. Adding this annotation to
|
|
|
|
your libraries will remove the need to have a separate `top` package
|
|
|
|
to install the printers.
|
|
|
|
|
|
|
|
For example, in the [uri](https://github.com/mirage/ocaml-uri)
|
|
|
|
library, the old printing function for `Uri.t` was:
|
|
|
|
|
|
|
|
```
|
|
|
|
val pp_hum : Format.formatter -> t -> unit
|
|
|
|
```
|
|
|
|
|
|
|
|
Just adding this annotation results in `Uri.t` values being automatically
|
|
|
|
pretty printed in this version of utop.
|
|
|
|
|
|
|
|
```
|
|
|
|
val pp_hum : Format.formatter -> t -> unit [@@ocaml.toplevel_printer]
|
|
|
|
```
|
|
|
|
|
|
|
|
There should be no downsides to adding this attribute to your
|
|
|
|
libraries, so we encourage community library maintainers to
|
|
|
|
use this attribute to improve the out-of-the-box experience
|
|
|
|
for users of their libraries within utop.
|
|
|
|
|
2012-10-29 09:48:35 +00:00
|
|
|
Creating a custom utop-enabled toplevel
|
|
|
|
---------------------------------------
|
|
|
|
|
2019-01-14 18:50:32 +00:00
|
|
|
### With Dune
|
2017-06-07 08:34:36 +00:00
|
|
|
|
|
|
|
The recommended way to build a custom utop toplevel is via
|
2019-01-14 18:50:32 +00:00
|
|
|
[Dune][dune]. The entry point of the custom utop must call
|
2017-06-07 08:34:36 +00:00
|
|
|
`UTop_main.main`. For instance write the following `myutop.ml` file:
|
|
|
|
|
|
|
|
```ocaml
|
|
|
|
let () = UTop_main.main ()
|
|
|
|
```
|
|
|
|
|
2019-01-14 18:50:32 +00:00
|
|
|
and the following dune file:
|
2017-06-07 08:34:36 +00:00
|
|
|
|
2020-01-03 22:26:17 +00:00
|
|
|
```elisp
|
2017-06-07 08:34:36 +00:00
|
|
|
(executable
|
2019-01-14 18:50:32 +00:00
|
|
|
(name myutop)
|
|
|
|
(link_flags -linkall)
|
|
|
|
(libraries utop))
|
2017-06-07 08:34:36 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
then to build the toplevel, run:
|
|
|
|
|
|
|
|
```
|
2019-01-14 18:50:32 +00:00
|
|
|
$ dune myutop.bc
|
2017-06-07 08:34:36 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
Note the `-linkall` in the link flags. By default OCaml doesn't link
|
|
|
|
unused modules, however for a toplevel you don't know in advance what
|
|
|
|
the user is going to use so you must link everything.
|
|
|
|
|
|
|
|
If you want to include more libraries in your custom utop, simply add
|
|
|
|
them to the `(libraries ...)` field.
|
|
|
|
|
2019-01-14 18:50:32 +00:00
|
|
|
Additionally, if you want to install this toplevel, add the two
|
2017-06-07 08:34:36 +00:00
|
|
|
following fields to the executable stanza:
|
|
|
|
|
2020-01-03 22:26:17 +00:00
|
|
|
```elisp
|
2017-06-07 08:34:36 +00:00
|
|
|
(public_name myutop)
|
2019-01-14 18:50:32 +00:00
|
|
|
(modes byte)
|
2017-06-07 08:34:36 +00:00
|
|
|
```
|
|
|
|
|
2019-01-14 18:50:32 +00:00
|
|
|
The `(modes ...)` field is to tell dune to install the byte-code
|
2017-06-07 08:34:36 +00:00
|
|
|
version of the executable, as currently native toplevels are not fully
|
|
|
|
suported.
|
|
|
|
|
2019-01-14 18:50:32 +00:00
|
|
|
[dune]: https://github.com/ocaml/dune
|
2017-06-07 08:34:36 +00:00
|
|
|
|
|
|
|
### Manually, with ocamlfind
|
|
|
|
|
|
|
|
This section describe methods using ocamlfind. These are no longer
|
|
|
|
tested, so there is no guarantee they still work.
|
|
|
|
|
2012-10-29 09:48:35 +00:00
|
|
|
If you want to create a custom toplevel with utop instead of the
|
|
|
|
classic one you need to link it with utop and its dependencies and
|
|
|
|
call `UTop_main.main` in the last linked unit. You also need to pass
|
|
|
|
the `-thread` switch when linking the toplevel.
|
|
|
|
|
|
|
|
The easiest way to do that is by using ocamlfind:
|
|
|
|
|
|
|
|
$ ocamlfind ocamlmktop -o myutop -thread -linkpkg -package utop myutop_main.cmo
|
|
|
|
|
|
|
|
Where `myutop_main.ml` contains:
|
|
|
|
|
|
|
|
```ocaml
|
|
|
|
let () = UTop_main.main ()
|
|
|
|
```
|
|
|
|
|
|
|
|
You can also use the `ocamlc` sub-command instead of `ocamlmktop`, in
|
|
|
|
this case you need to pass these thee extra arguments:
|
|
|
|
|
|
|
|
* `-linkall` to be sure all units are linked into the produced toplevel
|
|
|
|
* `-package compiler-libs.toplevel`
|
|
|
|
* `-predicates create_toploop`
|
|
|
|
|
|
|
|
With the last option ocamlfind will generate a small ocaml unit,
|
|
|
|
linked just before `myutop_main.cmo`, which will register at startup
|
|
|
|
packages already linked in the toplevel so they are not loaded again
|
|
|
|
by the `#require` directive. It does the same with the `ocamlmktop`
|
|
|
|
sub-command.
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
2014-05-10 06:48:41 +00:00
|
|
|
$ ocamlfind ocamlc -o myutop -thread -linkpkg -linkall -predicates create_toploop \
|
2012-10-29 09:48:35 +00:00
|
|
|
-package compiler-libs.toplevel,utop myutop.cmo
|
|
|
|
|
|
|
|
Note that if you are not using ocamlfind, you will need to do that
|
|
|
|
yourself. You have to call `Topfind.don't_load` with the list of all
|
|
|
|
packages linked with the toplevel.
|
2012-10-29 10:11:46 +00:00
|
|
|
|
|
|
|
A full example using ocamlbuild is provided in the
|
2014-05-10 06:48:41 +00:00
|
|
|
[examples/custom-utop](examples/custom-utop) directory.
|