We've released OCamlFormat 0.26.2 with compatibility with OCaml 5.2.
See full changelog
Changed
- Compatible with OCaml 5.2.0 (#2510, @gpetiot, @Julow)
Read the latest releases and updates from the OCaml ecosystem.
We've released OCamlFormat 0.26.2 with compatibility with OCaml 5.2.
We are pleased to announce the release of OCamlFormat 0.26.1!
This is the first OCamlFormat release to be compatible with OCaml 5.1.
We highlight notable formatting improvements below:
type t =
| Foo
| (* Redirect (None, lib) looks up lib in the same database *)
- Redirect of
- db option * (Loc.t * Lib_name.t)
+ Redirect of db option * (Loc.t * Lib_name.t)
+
object
keywordmodule type S = sig
- class tttttttttttt : aaaaaaaaaaaaaaaaaa:int -> bbbbbbbbbbbbbbbbbbbbb:float ->
+ class tttttttttttt :
+ aaaaaaaaaaaaaaaaaa:int ->
+ bbbbbbbbbbbbbbbbbbbbb:float ->
cccccccccccccccccccc
end
class type ct =
let open M in
- object
+object
val x : t
end
We've also fixed a few bugs. Attributes that were previously skipped are not preserved, and we fixed a crash that occured in the presence of nested modules.
Have a look at the full changelog to see the list of improvements, and don’t hesitate to share your feedback on this release on OCaml Discuss.
object
keyword in class types (#2425, @Julow)with module
(#2419, @Julow)We are thrilled to announce the release of OCamlFormat 0.26.0!
After almost 5 months of intense development, this release comes with a ton of consistency improvements and bug fixes. In particular, the handling of comments should be largely superior!
Have a look at the full changelog to see the list of improvements, and don't hesitate to share your feedback on this release on OCaml Discuss.
Items marked with an asterisk (*
) are changes that are likely to format
existing code differently from the previous release when using the default
profile.
--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.We are pleased to announce the release of OCamlFormat 0.25.1! This release contains several bug fixes, changes, and new features.
The library is also available through the ocamlformat-lib
package on opam. The ocamlformat
package only contains the binary.
We would like to thank all contributors for their valuable contributions to this release. Please see the complete changelog for more details.
We hope you enjoy this release and continue to find OCamlFormat a valuable tool for your OCaml projects. You can download ocamlformat.0.25.1
from the opam repository or GitHub.
Thank you for your support and feedback, and please don't hesitate to reach out if you have any questions or issues.
The OCamlFormat team
if-then-else
and break-cases
optionsStarting in OCamlFormat 0.25.1, we've also added new values to the if-then-else
and break-cases
options. Now you can use the vertical
value to format these expressions in a more readable and consistent way.
These options are not set by default but you can try them out by customizing your .ocamlformat
file as usual.
Here are a few examples:
if-then-else = vertical
- let epi = if Option.is_some next then fmt "@\n" else fmt_opt epi in
+ let epi =
+ if Option.is_some next then
+ fmt "@\n"
+ else
+ fmt_opt epi
+ in
- if tree_depth tree > depth then node_depth_truncate_ depth node
- else (* already short enough; don't bother truncating *)
+ if tree_depth tree > depth then
+ node_depth_truncate_ depth node
+ else
+ (* already short enough; don't bother truncating *)
node
break-cases = vertical
-| Ok (`Version | `Help) -> Stdlib.exit 0
-| Error _ -> Stdlib.exit 1
+| Ok (`Version | `Help) ->
+ Stdlib.exit 0
+| Error _ ->
+ Stdlib.exit 1
- ~f:(function `Int _ | `Float _ -> true | _ -> false)
+ ~f:(function
+ | `Int _
+ | `Float _ ->
+ true
+ | _ ->
+ false)
Formatting .mld
files as odoc documentation files is now possible! This will make it much easier to maintain high-quality documentation alongside your OCaml code.
This feature is only available in ocamlformat
for now, but keep an eye on the future dune
releases to know when dune fmt
will be able to format your .mld
files!
We fixed various issues related to indentation, alignment, and comments positioning.
Here are a few examples:
| [ node ] ->
( (if List.mem node ~set:integer_graph.(node)
- then Has_loop [ numbering.forth.(node) ]
- else No_loop numbering.forth.(node))
+ then Has_loop [ numbering.forth.(node) ]
+ else No_loop numbering.forth.(node))
, component_edges.(component) )
(let open Memo.O in
- let+ w = Dune_rules.Workspace.workspace () in
- Dune_engine.Execution_parameters.builtin_default
- |> Dune_rules.Workspace.update_execution_parameters w);
+ let+ w = Dune_rules.Workspace.workspace () in
+ Dune_engine.Execution_parameters.builtin_default
+ |> Dune_rules.Workspace.update_execution_parameters w);
- module Sel = (val if is_osx () then (module Mac)
- else if Sys.unix then (module Unix)
- else (module Fail) : Unix_socket)
+ module Sel =
+ (val if is_osx () then (module Mac)
+ else if Sys.unix then (module Unix)
+ else (module Fail)
+ : Unix_socket)
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)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)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)--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)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
.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)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]
.{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)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.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 OCamlformat[%ext (() [@attr])]
or the structure item (() [@attr]) ;;
let _ = ...
constructs (#1244, @emillon)(x >>= fun y -> y (* A *))
would be droppedmodule M = (val x : S (* A *))
[%a:]
(#1236, @emillon){< >}
(#1238, @emillon)(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 test
new%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