package ocamlformat
Install
Dune Dependency
Authors
Maintainers
Sources
sha256=b84b694ef7c957bc05f938c98c687da77645cddab1c5ec6ae270f6113175224e
sha512=88d0c4c1746c08f3bd34a0d1e1e34dda1496d1d96f613e2523923ce7d9e9e31b0e5cc7ab7f6634d04ea6354aa777972a248b9c7bc4f817b4ad357277e4da781e
Description
OCamlFormat is a tool to automatically format OCaml code in a uniform style.
Published: 30 Jan 2020
README
README.md
OCamlFormat
OCamlFormat is a tool to format OCaml code.
OCamlFormat works by parsing source code using the OCaml compiler's standard parser, deciding where to place comments in the parse tree, and writing the parse tree and comments in a consistent style.
See the source code of OCamlFormat itself and Infer for examples of the styles of code it produces.
Table of Contents
Features
Overview
OCamlFormat requires source code that meets the following conditions:
Does not trigger warning 50 (“Unexpected documentation comment.”). For code that triggers warning 50, it is unlikely that ocamlformat will happen to preserve the documentation string attachment.
Parses without any preprocessing, using the version of the standard ocaml (not camlp4) parser used to build ocamlformat. Attributes and extension points should be correctly preserved, but other mechanisms such as camlp4, cppo, etc. will not work.
Is either a module implementation (
.ml
), an interface (.mli
) or a sequence of toplevel phrases (.mlt
). dune files in ocaml syntax also work.
Under those conditions, ocamlformat is expected to produce output equivalent to the input. As a safety check in case of bugs, prior to terminating or modifying any input file, ocamlformat enforces the following checks:
The parse trees obtained by parsing the original and formatted files are equal up to some minor normalization (see
Normalize
.equal_impl
orequal_intf
).The documentation strings, and their attachment, has been preserved (implicit in the parse tree check).
The set of comments in the original and formatted files is the same up to their location.
Code style
There are a number of preset code style profiles, selected using the --profile
option by passing --profile=<name>
on the command line or adding profile = <name>
to an .ocamlformat configuration file. Each profile is a collection of settings for all options, overriding lower priority configuration of individual options. So a profile can be selected and then individual options can be overridden if desired.
The conventional
or default
profile aims to be as familiar and "conventional" appearing as the available options allow.
The ocamlformat
profile aims to take advantage of the strengths of a parsetree-based auto-formatter, and to limit the consequences of the weaknesses imposed by the current implementation. This is a style which optimizes for what the formatter can do best, rather than to match the style of any existing code. Instead of familiarity, the focus is on legibility, keeping the common cases reasonably compact while attempting to avoid confusing formatting in corner cases. General guidelines that have directed the design include:
Legibility, in the sense of making it as hard as possible for quick visual parsing to give the wrong interpretation, is of highest priority;
Whenever possible the high-level structure of the code should be obvious by looking only at the left margin, in particular, it should not be necessary to visually jump from left to right hunting for critical keywords, tokens, etc;
All else equal compact code is preferred as reading without scrolling is easier, so indentation or white space is avoided unless it helps legibility;
Attention has been given to making some syntactic gotchas visually obvious.
The compact
profile is similar to ocamlformat
but opts for a generally more compact code style.
The sparse
profile is similar to ocamlformat
but opts for a generally more sparse code style.
If no profile is selected, the conventional
one is used.
Options
The full options' documentation is available in [ocamlformat-help.txt] and through ocamlformat --help
. Options can be modified by the means of:
an .ocamlformat configuration file with an
option = VAL
lineusing the
OCAMLFORMAT
environment variable:OCAMLFORMAT=option=VAL,...,option=VAL
an optional parameter on the command line
a global
[@@@ocamlformat "option=VAL"]
attribute in the processed filean
[@@ocamlformat "option=VAL"]
attribute on an expression in the processed file
.ocamlformat files in the containing and all ancestor directories for each input file are used, as well as the global .ocamlformat file defined in $XDG_CONFIG_HOME/ocamlformat
. The global .ocamlformat file has the lowest priority, then the closer the directory is to the processed file, the higher the priority.
When the option --enable-outside-detected-project
is not set, .ocamlformat files outside of the project (including the one in XDG_CONFIG_HOME
) are not read. 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 no config file is found, formatting is disabled.
An .ocamlformat-ignore
file specifies files that OCamlFormat should ignore. Each line in an .ocamlformat-ignore
file specifies a filename relative to the directory containing the .ocamlformat-ignore
file. Lines starting with #
are ignored and can be used as comments.
Installation
OCamlFormat can be installed with opam
:
opam install ocamlformat
Alternately, see ocamlformat.opam
for manual build instructions.
Editor setup
Disable outside project
As mentioned in the Options section, when the option --disable-outside-detected-project
is set, .ocamlformat files outside of the project (including the one in XDG_CONFIG_HOME
) are not read. 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 no config file is found, then the formatting is disabled.
This feature is often the behavior you can expect from OCamlFormat when it is directly run from your text editor, so it is advised to use this option.
Emacs setup
add
$(opam config var share)/emacs/site-lisp
toload-path
(as done byopam user-setup install
)add
(require 'ocamlformat)
to.emacs
optionally add the following to
.emacs
to bindC-M-<tab>
to the ocamlformat command and install a hook to run ocamlformat when saving:
(add-hook 'tuareg-mode-hook (lambda ()
(define-key tuareg-mode-map (kbd "C-M-<tab>") #'ocamlformat)
(add-hook 'before-save-hook #'ocamlformat-before-save)))
To pass the option --disable-outside-detected-project
(or --disable
) to OCamlFormat:
run
emacs
run
M-x customize-group⏎
then enterocamlformat⏎
select the Ocamlformat Enable item
select the OCamlformat mode in the Value Menu:
Enable
(by default),Disable
orDisable outside detected project
save the buffer (
C-x C-s
) then enteryes⏎
and exit
Other OCamlFormat options can be set in .ocamlformat configuration files.
Vim setup
be sure the
ocamlformat
binary can be found in PATHinstall the Neoformat plugin
Optional: You can change the options passed to OCamlFormat (to use the option --disable-outside-detected-project
for example), you can customize NeoFormat with:
let g:neoformat_ocaml_ocamlformat = {
\ 'exe': 'ocamlformat',
\ 'no_append': 1,
\ 'stdin': 1,
\ 'args': ['--disable-outside-detected-project', '--name', '"%:p"', '-']
\ }
let g:neoformat_enabled_ocaml = ['ocamlformat']
Documentation
OCamlFormat is documented in its man page and through its internal help:
ocamlformat --help
man ocamlformat
You can also view it online.
Reason
OCamlFormat is influenced by and follows the same basic design as refmt
for Reason, but outputs OCaml instead of Reason.
This tool is not able to deal directly with Reason code (*.re
/*.rei
files), but it is possible to first convert these files to ocaml syntax using refmt -p ml
and then running ocamlformat
on this output.
Community
developers mailing list: http://lists.ocaml.org/listinfo/ocamlformat-dev
See CONTRIBUTING for how to help out.
License
OCamlFormat is MIT-licensed.
Dependencies (12)
Dev Dependencies (5)
-
ocp-indent
with-test
-
dune
with-test & < "3.0"
-
cmdliner
with-test & < "1.1.0"
-
alcotest
with-test
-
ocaml
with-test & >= "4.08" & < "5.2"
Used by (59)
- ask
- ask-integrator
- autofonce
- autofonce_config
- autofonce_core
- autofonce_lib
- autofonce_m4
- autofonce_misc
- autofonce_patch
- autofonce_share
- awsm-codegen
-
bastet
< "2.0.0"
- bitpack_serializer
- diff
- drom
- drom_lib
- drom_toml
-
ez_cmdliner
>= "0.2.0"
-
ez_config
>= "0.2.0"
-
ez_file
>= "0.2.0"
-
ez_hash
< "0.5.3"
- ez_opam_file
- ez_search
- ez_subst
- fromager
- header-check
-
js_of_ocaml-webgpu
>= "0.2"
-
letters
>= "0.2.0" & != "0.3.1"
- melange-fest
-
melange-json
>= "1.2.0"
-
melange-radix-icons
>= "0.1.0"
- mlx
- module-graph
-
noCanren
>= "0.3.0~alpha1"
-
OCanren
>= "0.3.0~alpha1"
-
OCanren-ppx
= "0.3.0~alpha1"
-
ocaml-lsp-server
< "1.8.0"
- ocp-search
-
ocplib_stuff
>= "0.3.0"
-
opam-bin
>= "0.9.5"
-
opam_bin_lib
>= "0.9.5"
-
owi
>= "0.2"
- polars
- polars_async
- ppx_deriving_jsonschema
-
psmt2-frontend
>= "0.3.0"
-
pyml_bindgen
< "0.1.2"
-
rea
< "0.2.0"
- red-black-tree
-
scaml
>= "1.2.0"
-
sihl
< "0.1.0"
- solidity-alcotest
- solidity-common
- solidity-parser
- solidity-test
- solidity-typechecker
-
spotify_ml
>= "push"
- styled-ppx
-
yocaml
>= "2.0.0"
Conflicts
None