OCamlFormat 0.8

by Guillaume Petiot on Oct 17th, 2018

We are proud to announce the release of OCamlFormat 0.8 (available on opam). To ease the transition from the previous 0.7 release here are some highlights of the new features of this release. The full changelog is available on the project repository.

Precedence of options

In the previous version you could override command line options with .ocamlformat files configuration. 0.8 fixed this so that the OCamlFormat configuration is first established by reading .ocamlformat and .ocp-indent files:

margin = 77
wrap-comments = true

By default, these files in current and all ancestor directories for each input file are used, as well as the global configuration defined in $XDG_CONFIG_HOME/ocamlformat. The global $XDG_CONFIG_HOME/ocamlformat configuration has the lowest priority, then the closer the directory is to the processed file, the higher the priority. In each directory, both .ocamlformat and .ocp-indent files are read, with .ocamlformat files having the higher priority.

For now ocp-indent options support is very partial and is expected to be extended in the future.

Then the parameters can be overriden with the OCAMLFORMAT environment variable:

OCAMLFORMAT=field-space=tight,type-decl=compact

and finally the parameters can be overriden again with the command lines parameters.

Reading input from stdin

It is now possible to read the input from stdin instead of OCaml files. The following command invokes OCamlFormat that reads its input from the pipe:

echo "let f x = x + 1" | ocamlformat --name a.ml -

The - on the command line indicates that ocamlformat should read from stdin instead of expecting input files. It is then necessary to use the --name option to designate the input (a.ml here).

Preset profiles

Preset profiles allow you to have a consistent configuration without needing to tune every option.

Preset profiles set all options, overriding lower priority configuration. A preset profile can be set using the --profile (or -p) option. You can pass the option --profile=<name> on the command line or add profile = <name> in an .ocamlformat configuration file.

The available profiles are:

  • default sets each option to its default value
  • compact sets options for a generally compact code style
  • sparse sets options for a generally sparse code style
  • janestreet is the profile used at JaneStreet

To get a better feel of it, here is the formatting of the mk_callback function from the OCaml compiler with the compact profile:

let mk_callback rest name desc = function
  | None -> nothing
  | Some f -> (
      fun () ->
        match rest with
        | [] -> f name None
        | (hidden, _) :: _ -> f name (Some (desc, hidden)) )

then the same function formatted with the sparse profile:

let mk_callback rest name desc = function
  | None ->
      nothing
  | Some f ->
      fun () ->
        ( match rest with
        | [] ->
            f name None
        | (hidden, _) :: _ ->
            f name (Some (desc, hidden)) )

Project root

The project root of an input file is taken to be the nearest ancestor directory that contains a .git or .hg or dune-project file. If the new option --disable-outside-detected-project is set, .ocamlformat configuration files are not read outside of the current project. If no configuration file is found, formatting is disabled.

A new option, --root allows to specify the root directory for a project. If specified, OCamlFormat only takes into account .ocamlformat configuration files inside the root directory and its subdirectories.

Credits

This release also contains many other changes and bug fixes that we cannot detail here. Check out the full changelog.

Special thanks to our maintainers and contributors for this release: David Allsopp, Josh Berdine, Hugo Heuzard, Brandon Kase, Anil Madhavapeddy and Guillaume Petiot.