Items marked with an asterisk (*) are changes that are likely to format existing code differently from the previous release when using the default profile. This started with version 0.26.0.
--numeric feature (#2333, #2357, @gpetiot)let f (type a) :> a M.u = .. (#2399, @Julow)module T = (val (x : (module S))) (#2370, @Julow)then begin end (#2369, @Julow)fun _ : _ -> (#2352, @Julow)(::) (#2347, @Julow)as-patterns that have parentheses (#2359, @Julow)@@ let+ x = ... (#2315, #2396, @Julow) It was formatted differently than @@ let x = ....fun (type a) -> following fun x -> (#2294, @Julow)((module M) : (module S)) is formatted as (module M : S)) (#2280, #2300, @gpetiot, @Julow)~label:(fun ... (#2271, #2291, #2293, #2298, #2398, @Julow) The fun keyword is docked where possible and the arguments are indented to avoid confusion with the body.max-indent option is not set (#2131, @hhugo, @gpetiot)enable/disable floating attributes (#2156, @gpetiot).ocamlformat-ignore under Windows (#2206, @nojb)initializer keyword (#2145, @gpetiot)(struct end) vs ()) (#2135, #2146, @trefis, @gpetiot)((module X) : (module Y)) vs (module X : Y)) (#2136, @trefis, @gpetiot)Preserve syntax and improve readability of indexop-access expressions (#2150, @trefis, @gpetiot)
if carrying attributes (#2167, @trefis, @gpetiot)ocamlformat package now only contains the binary, the library is available through the ocamlformat-lib package (#2230, @gpetiot)break-colon option to decide whether to break before or after the : symbol in value binding declarations and type constraints. This behavior is no longer ensured by ocp-indent-compat. (#2149, @gpetiot).mld files as odoc documentation files (#2008, @gpetiot)vertical for option if-then-else (#2174, @gpetiot)vertical for option break-cases (#2176, @gpetiot)wrap-or-vertical for option break-infix that only wraps high precedence infix ops (#1865, @gpetiot)Support odoc-parser.2.0.0 (#2123, @gpetiot)
odoc-parser{m ...} available in doc-comments{math ...} available in doc-commentsbench binary is not distributed anymore to avoid name collisions (#2104, @gpetiot)indicate-multiline-delimiters (#2116, @gpetiot).ocp-indent files (#2103, @gpetiot)max-indent = 2 (#2099, @gpetiot)| under keyword instead of parenthesis (#2102, @gpetiot)compact and sparse are now removed (#2075, @gpetiot)align-cases, align-constructors-decl and align-variants-decl are now removed (#2076, @gpetiot)disable-outside-detected-project is now removed (#2077, @gpetiot)$XDG_CONFIG_HOME or $HOME/.config) is only applied when no project is detected, --enable-outside-detected-project is set, and no applicable .ocamlformat file has been found. Global and local configurations are no longer used at the same time. (#2039, @gpetiot)ocaml-version to a fixed version (4.04.0) by default to avoid reproducibility issues and surprising behaviours (#2064, @kit-ty-kate)--numeric=X-Y into --range=X-Y and --numeric (flag). For now --range can only be used with --numeric. (#2073, #2082, @gpetiot)(*= ... *) for verbatim comments (#2028, @gpetiot)--print-config displays a warning when an .ocamlformat file defines redundant options (already defined by a profile) (#2084, @gpetiot):= when assignment-operator=end-line (#1985, @gpetiot)wrap-comments should only impact non-documentation comments, wrapping invalid docstrings would cause the whole file to not be formatted (#1988, @gpetiot)comment-check, disable, max-iters, ocaml-version, and quiet (#1995, @gpetiot).(x >>= (fun () -> ())) [@a] (#2013, @emillon)More expressions are considered "simple" (not inducing a break e.g. as an argument of an application):
--parse-toplevel-phrases. Toplevel phrases are supported when they are located in doc-comments blocks and cinaps comments. Whole input files can also be formatted as toplevel phrases with the flag --repl-file.Csexp.t types instead of Sexplib0.Sexp.t..ocamlformat (#2011, @panglesd, @Julow){@ocaml kind=toplevel env=e1[ code ]}compact and sparse are now deprecated and will be removed by version 1.0 (#1803, @gpetiot)Options that are not set by the preset profiles are now deprecated and will be removed by version 1.0:
align-cases, align-constructors-decl and align-variants-decl (#1793, @gpetiot)disambiguate-non-breaking-match (#1805, @gpetiot)break-before-in (#1888, @gpetiot)break-cases={toplevel,all} (#1890, @gpetiot)break-collection-expressions (#1891, @gpetiot)break-fun-decl=smart (#1892, @gpetiot)break-fun-sig=smart (#1893, @gpetiot)break-string-literals (#1894, @gpetiot)break-struct (#1895, @gpetiot)extension-indent (#1896, @gpetiot)function-indent (#1897, @gpetiot)function-indent-nested (#1898, @gpetiot)if-then-else={fit-or-vertical,k-r} (#1899, @gpetiot)indicate-multiline-delimiters=closing-on-separate-line (#1900, @gpetiot)indent-after-in (#1901, @gpetiot)let-binding-indent (#1902, @gpetiot)let-binding-spacing=sparse (#1903, @gpetiot)match-indent (#1904, @gpetiot)match-indent-nested (#1905, @gpetiot)module-item-spacing=preserve (#1906, @gpetiot)nested-match (#1907, @gpetiot)parens-tuple-patterns (#1908, @gpetiot)sequence-style=before (#1909, @gpetiot)stritem-extension-indent (#1910, @gpetiot)type-decl-indent (#1911, @gpetiot){|...|} (#1754, @nojb, @hhugo)*, %, #-ops) (#1776, @gpetiot)indicate-multiline-delimiters=closing-on-separate-line (#1786, @gpetiot)foo ~(x:int) instead of the explicit foo ~x:(x:int). (ocaml#10434) (#1756, #1759, @gpetiot). This syntax is only produced when the output syntax is at least OCaml 4.14.ocaml-version option to select the version of OCaml syntax of the output (#1759, @gpetiot)begin%ext syntax for infix opererator expressions (#1653, @gpetiot);; tokens (#1688, @gpetiot)odoc-parser instead of odoc (#1683, #1713, @kit-ty-kate, @jonludlam, @julow). The parser from odoc has been split from the main odoc package and put into its own package, odoc-parser.Implement OCaml 4.13 features (#1680, @gpetiot)
Emacs integration (disabled for ocamlformat < 0.19.0):
tools/build-mingw64.sh is provided to build a native Windows binary of ocamlformat using mingw64 toolchain under Cygwin.let open with closing-on-separate-line (#1612, @Julow)bisect_ppx (#1550, @tmattio)ocamlformat-rpc and a new library ocamlformat-rpc-lib (#1586, @gpetiot, @voodoos)String.get and similar calls used to be automatically rewritten to their corresponding infix form .(), that was incorrect when using the -unsafe compilation flag. Now the concrete syntax of these calls is preserved.if%ext with if-then-else=keyword-first (#1419, #1543, @gpetiot)match and try keywords (#1458, @gpetiot)Clean up ocamlformat.el for submission to MELPA (#1476, #1495, @bcc32)
ocamlformat.el (#1474, @bcc32)ocamlformat.el buffer replacement for MacOS Emacs (#1481, @juxd)function match (#1498, @gpetiot)open%ext M will not get rewritten to [%%ext open M].Use ppxlib instead of ocaml-migrate-parsetree 1.x. (#1482, @emillon)
{i blah} in docstrings (#1346, @jberdine)#**# or #**. where ** can be 0 or more operator chars are considered getter operators and are not surrounded by spaces, as opposed to regular infix operators (#1376, @gpetiot)function body of a fun (#1343, @jberdine)*compilation* buffer on successful reformat (#1350, @jberdine)wrap-comments=false and ocp-indent-compat=true are set to avoid interfering with ocp-indent indentation. (#1352, @gpetiot)[]{} must not be escaped in the arguments of @raise, @author, @version and others.(* *), (** *) and (*$ *) (#1407, @gpetiot)Backport the following PRs:
Merge doc-comments-val option with doc-comments. The placement of documentation comments on val and external items is now controled by doc-comments.
doc-comments=after becomes doc-comments=after-when-possible to take into account the technical limitations of ocamlformat;doc-comments=before is unchanged;doc-comments-val is now replaced with doc-comments. To reproduce the former behaviors
doc-comments=before + doc-comments-val=before: now use doc-comments=before;doc-comments=before + doc-comments-val=after: now use doc-comments=before-except-val;doc-comments=after + doc-comments-val=before: this behavior did not make much sense and is not available anymore;doc-comments=after + doc-comments-val=after: now use doc-comments=after-when-possible. (#1358, @jberdine, @Julow, @gpetiot). This reverts changes introduced in 0.14.1 (#1335) and 0.14.0 (#1012).doc-comments is changed to after (#1335, @Julow). This reverts a change introduced in 0.14.0 (#1012).doc-comments option (#1331, @Julow). This reverts a change introduced in 0.14.0 (#1293).--format-invalid-files to print unparsable parts of the input as verbatim text. This feature is still experimental. (#1026, @gpetiot)module M = functor (K : S) -> struct end and module M (K : S) = struct end would be formatted as the latter, the original syntax is now preserved.doc-comments-val=before|after (#1012, @Julow). This option set the placement of documentation comment on val and external only. It is set to after by default.doc-comments is changed from after to before (#1012, #1325, @Julow). This affects both conventional (default) and ocamlformat profiles.Some options are now deprecated:
doc-comments (#1293, #1012). This option depends on a flawed heuristic. It is replaced by doc-comments-val for val and external declarations. There is no equivalent to this option in the general case.escape-chars, escape-strings and extension-sugar (#1293). These options are rarely used and their default behavior is considered to be the right behavior.row_field attributes and the label or arguments, to be consistent with the non-polymorphic case. (#1299, @CraigFe)let open (#1229, @Julow). eg. M.f (M.(x) [@attr]) would be formatted to M.f M.(x) [@attr], which would crash OCamlformatRemove unecessary parentheses with attributes in some structure items:
[%ext (() [@attr])] or the structure item (() [@attr]) ;;let _ = ... constructs (#1244, @emillon)Fix some bugs related to comments:
(x >>= fun y -> y (* A *)) would be droppedmodule M = (val x : S (* A *))[%a:] (#1236, @emillon){< >} (#1238, @emillon)Retain attributes on various AST nodes:
(a.x <- b) [@a] (#1284, @CraigFe)(a <- b) [@a] (#1288, @CraigFe)(a.(b)) [@a] (#1300, @CraigFe)(a; b) [@a] (#1291, @CraigFe){foo : < .. > [@a]} and { foo : < .. > } (#1296, @CraigFe)f ((0, 0) [@a]) would be formatted to f (0, 0) [@a], crashing OCamlformat.>] when an object type is contained in an extension point or attribute payload (#1298, @CraigFe)(0).*(0) (#1304, @Julow). It was formatting to 0.*(0) which parses as an other expression.(**) would be formatted to (***).class (#1289, @emillon)let f ?a:(A) = () rather than the unparsable let f ?a:A = () (#1305, @CraigFe)--margin-check to emit a warning if the formatted output exceeds the margin (#1110, @gpetiot)wrap-comments is unset (#1138, #1159, @Julow)ocamlformat_reason (#254, #1185, @emillon). This tool has never been released to opam, has no known users, and overlaps with what refmt can do.ocamlformat-diff (#1205, @gpetiot). This tool has never been released to opam, has no known users, and overlaps with what merge-fmt can do.break-cases=fit (#1167, @Julow). This also fixes an unstable comment bug in or-patternsversion-check (#1135, @Wilfred)break-separators=after-and-docked (#1130, @gretay-js)profile = ocamlformat in your .ocamlformat.--opt and --no-opt` are available on the CLI for any boolean option "opt". Previously, only one of them were available depending on the default value.break-string-literals (#1057, @gpetiot). wrap, newlines and newlines-and-wrap values of break-string-literals are removed. auto replaces them, it is equivalent to newlines-and-wrap.after-and-docked value of break-separators is removed and is replaced by a new dock-collection-brackets option.begin and end keywords in if-then-else (#978, @Julow). Previously, begin/end keywords around if-then-else branches were turned into parentheses.sequence-blank-line=preserve-one for let bindings (#1077, @Julow). Preserve a blank line after let .. in when sequence-blank-line set to preserve-one. Previously, only blank lines after ; could be preserved.#directives in .ml files. Previously, files containing a directive needed to be parsed as "use file". The "use file" mode is removed and --use-file is now the same as --impl.--name, require kind, forbid --inplace, allow --check, make --enable-outside-detected-project implicit when reading from stdin (#1018, @gpetiot)(*$ code *) and code blocks in documentation comments (** {[ code ]} *).max-indent (#1105, @gpetiot)Pmty_with (#1103, @jberdine)break-cases=all (#1002, @gpetiot)Fmt API in case Fmt.t goes abstract (#1106, @emillon)Translation_unit (#1078, @gpetiot)sequence_blank_line (#1075, @Julow)Fmt_ast (#1059, @gpetiot)test_branch.sh (#1033, @gpetiot)test_branch.sh and CI checking of CHANGES.md (#1032, #1034, @Julow)test_branch.sh and bisect.sh (#1027, @gpetiot)bisect_ppx dependency and clean the Makefile (#1005, @Julow)CHANGES.md log file again (#1023, @gpetiot)CONTRIBUTING.md (#1007, @gpetiot)--ignore-invalid-option flag is added to ignore invalid options in .ocamlformat files.--doc-comments (#982, @Julow)fmt_code (#974, @gpetiot)Makefile (#973, @hhugo)let%ext (#873, @gpetiot):= (#780, @gpetiot); _ (#549, @jberdine):: (#452, @jberdine)function%ext (#416, @hhugo)while%ext/for%ext (@hhugo)# infix ops (@hhugo)in (#328, @jberdine)make -C test (@jberdine)+/- (@hhugo)%; (@hhugo)not when infix op arg (@jberdine)function cases (@jberdine)>] which is an unparsable keyword (#171, @hhugo)module type of (@jberdine)not to be trivial if their arg ismake -C testnew%js (#136, @hhugo)(type a b c) (#142, hhugo){ !e with a } (#138, @hhugo)(universe) support in jbuilder 1.0+beta20Pexp_new expressions (#76, @smondet)Pexp_send _ expressions (#72, @smondet)[][ and < or > in variant types